package net.danielseidl.ludumdare.ld48.tile;

import java.util.logging.Logger;

import net.danielseidl.ludumdare.ld48.Game;
import net.danielseidl.ludumdare.ld48.level.Level;

/**
* Used for storing the tile data shown by the game viewer. When 
* the player moves on the map, the tile map will change as necessary.
*
 * @author    Daniel Seidl - info@daniel-seidl.net
*/
public class TileMap
	{
	private Logger LOGGER = Logger.getLogger(TileMap.class.getName());
	
	private Game game;
	
	private int width;
	private int height;
	
	private int tilesWidth;
	private int tilesHeight;
	
	private Tile[][] tilesLayerBelow;
	private Tile[][] tilesLayerLevel;
	
	private int paintStartX = 0;
	private int paintStartY = 0;
	
	/**
	 * Creates a new tile map based on the given width and height.
	 * @param width The width of the window.
	 * @param height The height of the window.
	 * @param game The game instance to work with.
	 */
	public TileMap(int width, int height, Game game)
		{
		this.game = game;		
		
		// Saving the window size for later use.
		this.width = width;
		this.height = height;
		
		// Calculate the needed size of the tile map.
		this.tilesWidth = (this.width / 32) + 4;
		this.tilesHeight = (this.height / 32) + 4;
		if (this.tilesWidth % 2 == 0)
			{
			this.tilesWidth++;
			}
		if (this.tilesHeight % 2 == 0)
			{
			this.tilesHeight++;
			}
		
		// Define the dimensions of the array storing the needed tiles.
		this.tilesLayerBelow = new Tile[this.tilesWidth][this.tilesHeight];
		this.tilesLayerLevel = new Tile[this.tilesWidth][this.tilesHeight];
		
		// Give some debug information to the console manager.
		this.LOGGER.info("created tile map with width " + this.tilesWidth + " tiles and height " + this.tilesHeight + " tiles = " + (this.tilesWidth * this.tilesHeight) + " tiles");
		
		// Calculate the paint position.
		this.setPaintStart();
		
		// Update the tiles for the view.
		this.updateTilesForView();
		}
	
	/**
	 * Calculates the x and y start location for painting the tile map.
	 */
	public void setPaintStart()
		{
		int[] p = this.game.getPlayer().getLocation();
		this.paintStartX = -((((this.tilesWidth - 1) / 2) * 32) + p[2]) + (this.width / 2);
		this.paintStartY = -((((this.tilesHeight - 1) / 2) * 32) + p[3]) + (this.height / 2);
		}
	
	/**
	 * Update the stored tile map with the newly needed tiles.
	 */
	public void updateTilesForView()
		{		
		// Calculate where the needed tiles are in the level.
		int[] p = this.game.getPlayer().getLocation();
		int startX = p[0] - (this.tilesWidth - 1) / 2;
		int startY = p[1] - (this.tilesHeight - 1) / 2;
		int endX = startX + this.tilesWidth;
		int endY = startY + this.tilesHeight;
			
		// Get the current level instance.
		Level level = this.game.getLevel();

		// Get all the needed tiles from the level and store them in the tile map.
		for (int i = startY, iC = 0; i < endY; i++, iC++)
			{
			for (int j = startX, jC = 0; j < endX; j++, jC++)
				{
				this.tilesLayerBelow[jC][iC] = level.getTileFromLayerBelow(j, i);
				this.tilesLayerLevel[jC][iC] = level.getTileFromLayerLevel(j, i);
				}
			}
		}
	
	/**
	 * Returns the stored tiles of the layer below the player for the level view.
	 * @return The stored tiles of the layer below the player.
	 */
	public Tile[][] getTilesLayerBelowForView()
		{
		return this.tilesLayerBelow;
		}
	
	/**
	 * Returns the stored tiles of the layer same as the player for the level view.
	 * @return The stored tiles of the layer same as the player.
	 */
	public Tile[][] getTilesLayerLevelForView()
		{
		return this.tilesLayerLevel;
		}
	
	/**
	 * Returns the painting start location on the x-axes.
	 * @return The x-axes' painting start location.
	 */
	public int getPaintStartX()
		{
		return this.paintStartX;
		}

	/**
	 * Returns the painting start location on the y-axes.
	 * @return The y-axes' painting start location.
	 */
	public int getPaintStartY()
		{
		return this.paintStartY;
		}
	
	/**
	 * Returns the width in tiles.
	 * @return The width in tiles.
	 */	
	public int getTilesWidth()
		{
		return this.tilesWidth;
		}

	/**
	 * Returns the height in tiles.
	 * @return The height in tiles.
	 */	
	public int getTilesHeight()
		{
		return this.tilesHeight;
		}
	}